# -*- coding: utf-8 -*-
from enum import Enum
from typing import List, Optional
from datetime import date

from fastapi import APIRouter, Cookie, Header, Path, Query
from pydantic import BaseModel, Field

app03 = APIRouter()

"""Path Parameters and Number Validations 路径参数和数字验证"""


@app03.get('/path/parameters')
async def path_params01():
    return {'message': 'this is a message'}


# 路由的顺序就是函数的顺序，如果传入parameters，则会使用第一个接口，因为相同名称它在前
@app03.get('/path/{parameters}')
async def path_params01(parameters: str):
    return {'message': parameters}


# 枚举类型验证
class CityName(Enum):
    BeiJing = 'beijing'
    ShangHai = 'shanghai'


@app03.get('/enum/{city}')
async def latest(city: CityName):
    if city == CityName.BeiJing:
        return {'city_name:': city}
    elif city == CityName.ShangHai:
        return {'city_name:': city}
    return {'city_name': 'unknown city'}


# 通过 path 传递路径
@app03.get('/files/{file_path:path}')
async def filepath(file_path: str):
    return f"The File Path is {file_path}"


# 最大最小值
@app03.get('/Path/{num}')
async def path_params_validate(num: int = Path(..., title='Your number', description='无描述', ge=1, le=10)):
    return num


"""Query Parameters and String Validations 查询参数和字符串验证"""


# 页数，验证选填字段
@app03.get('/query')
def page_limit(page: int, limit: Optional[int] = None):
    if limit:
        return {'page': page, 'limit': limit}
    return {'page': page}


# bool验证，yes,on,1,true 会返回true
@app03.get('/query/bool/conversion')
def type_conversion(param: bool = False):
    return param


# 数据长度,正则，列表验证
@app03.get('/query/validations')
def query_params_validate(
        value: str = Query(..., min_length=8, max_length=16, regex='^a'),
        values: List[str] = Query(default=['v1', 'v2'], alias='alias_name')  # alias：参数别名
):
    return value, values


"""Request Body and Fields 请求体和字段"""


class CityInfo(BaseModel):
    """定义数据格式"""
    name: str = Field(..., example='BeiJing')  # example：示例值，值不会验证，用来告诉前端人员name是干嘛的
    country: str
    conunty_code: str = None  # 给一个默认值
    conunty_population: int = Field(default=800, title='国家人口数量', ge=800)

    # 子类：数据示例
    class Config:
        schema_extra = {
            'example': {
                'name': 'Shanghai',
                'country': 'China',
                'conunty_code': 'CN',
                'conunty_population': 1400000000
            }
        }


@app03.post('/request_body/city')
def city_info(city: CityInfo):
    return city.dict()


"""Request Body + Path parameters + Query parameters 多参数混合"""


@app03.put('/request_body/city/{name}')
def mix_city_info(
        # 路径参数
        name: str,
        # 请求体
        city01: CityInfo,
        city02: CityInfo,
        # 数据查询验证
        confirmed: int = Query(ge=0, description='确诊数', default=0),
        death: int = Query(ge=0, description='死亡数', default=0)
):
    if name == 'shanghai':
        return {'shanghai': {'confirmed': confirmed, 'death': death}}
    else:
        return city01.dict(), city02.dict()


"""Request Body - Nested Models 数据格式嵌套的请求体"""


class Data(BaseModel):
    city: List[CityInfo] = None  # 嵌套请求体
    date: date  # 额外数据类型，还有uuid bytes 等，请参考官方文档
    confirmed: int = Field(ge=0, description='确诊数', default=0)
    death: int = Field(ge=0, description='死亡数', default=0)
    recovered: int = Field(ge=0, description='痊愈数', default=0)


@app03.put('/request_body/nested')
def nested_data(data: Data):
    return data


"""Cookie 和 Header 参数"""


# 定义 cookie 需要使用 fastapi Cookie 类
@app03.get('/cookie')
def cookie(cookie_id: Optional[str] = Cookie(None)):  # 定义Cookie参数需要使用Cookie类
    return {'cookie': cookie_id}


@app03.get('/header')
def header(user_agent: Optional[str] = Header(None, convert_underscores=True), x_token: List[str] = Header(None), ):
    """
    :param user_agent: convert_underscores=True：将 user_agent 转化为 user-agent
    :param x_token: 包含多个值的列表
    :return: 
    """
    return {'User_Agent': user_agent, 'x_token': x_token}
